/**
 * SWFWheel - remove dependencies of mouse wheel on each browser.
 *
 * Copyright (c) 2008 - 2009 Spark project (www.libspark.org)
 *
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 */
package org.libspark.ui;

    import flash.display.InteractiveObject;
    import flash.display.Stage;
    import flash.events.MouseEvent;
    import flash.external.ExternalInterface;
    import flash.system.Capabilities;
	import haxe.Resource;

    /**
     *
     */
    class SWFWheel
     {
        public function new() { }
        
        public static var available(get, null) :Bool;
        public static var isReady(get, null) :Bool;
        public static var EXECUTE_LIBRARY_FUNCTION:String = "SWFWheel.join";
        public static var CHECK_FORCE_EXTERNAL_FUNCTION:String = "SWFWheel.force";
        public static var DEFINE_LIBRARY_FUNCTION:String =  Resource.getString('SWFWheel');

        static var _stage:Stage;
        static var _item:InteractiveObject;
        static var _event:MouseEvent;

        /**
         *  initialize the SWFWheel hack.
         *
         *  @param stage                Stage object.
         */
        public static function initialize(stage:Stage):Void
        {
            //trace((!available || isReady));
			if (!available || isReady) return;

            _stage = stage;

            // define javascript library.
            ExternalInterface.call(DEFINE_LIBRARY_FUNCTION);
            // start light hack.
            ExternalInterface.call(EXECUTE_LIBRARY_FUNCTION, ExternalInterface.objectID);

            // check the environment.
            var mac:Bool = Capabilities.os.toLowerCase().indexOf("mac") != -1;
            var force:Bool = cast(ExternalInterface.call(CHECK_FORCE_EXTERNAL_FUNCTION, ExternalInterface.objectID));

            // ignore no mac, no safari.
            if(!mac && !force) return;

            trace('start deep hack');
            //  start deep hack.
            _stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoved);
            ExternalInterface.addCallback('externalMouseEvent', externalMouseEvent);
        }

        /**
         *
         *  @return bool        if already initialized, this property is true. otherwize it is false.
         */
        public static function get_isReady():Bool
        {
            return _stage != null;
        }

        /**
         *
         *  @return bool        if SWFWheel is available, this property is true. otherwite it is false.
         */
        public static function get_available():Bool
        {
            var f:Bool = false;

            if (!ExternalInterface.available) return f;

            try
            {
                f = ExternalInterface.available;
            }
            catch (e:Dynamic)
            {
                //  FIXME:should show full stack trace?
                //trace(e.getStackTrace());
                trace("Warning:turn off SWFWheel because can't access external interface.");
            }
            return f;
        }

        /**
         *  will execute when mouse moved.
         *
         *  @param  event           MouseEvent object.
         */
        static function mouseMoved(event:MouseEvent):Void
        {
            _item = cast(event.target);
            _event = event;
			//trace(_item);
        }

        /**
         *  will execute when dispatch `mouse wheel` event on swf content layer.
         *
         *  @param  delta           mouse wheel delta.
         */
        static function externalMouseEvent(delta:Float):Void
        {
            //  FIXME:should create dummy parameters?
            if (_event == null || _item == null) return;

            var event:MouseEvent = new MouseEvent(
                    MouseEvent.MOUSE_WHEEL,
                    true,
                    false,
                    _event.localX,
                    _event.localY,
                    _event.relatedObject,
                    _event.ctrlKey,
                    _event.altKey,
                    _event.shiftKey,
                    _event.buttonDown,
                    Std.int(delta)
                );
            _item.dispatchEvent(event);
        }
    }
